﻿using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Waf.Applications;
using System.Waf.Applications.Services;
using HighLandirect.Applications.Properties;
using HighLandirect.Applications.Services;
using HighLandirect.Applications.ViewModels;
using HighLandirect.Applications.Views;
using HighLandirect.Domain;

namespace HighLandirect.Applications
{
    [Export]
    public class ProductController : Controller
    {
        private readonly CompositionContainer container;
        private readonly IEntityService entityService;
        private readonly ShellViewModel shellViewModel;
        private readonly ProductViewModel productViewModel;
        private readonly DelegateCommand addNewCommand;
        private readonly DelegateCommand removeCommand;
        private ProductListViewModel productListViewModel;


        [ImportingConstructor]
        public ProductController(CompositionContainer container, IEntityService entityService, ShellViewModel shellViewModel,
            ProductViewModel productViewModel)
        {
            this.container = container;
            this.entityService = entityService;
            this.shellViewModel = shellViewModel;
            this.productViewModel = productViewModel;
            this.addNewCommand = new DelegateCommand(AddNewProduct, CanAddNewProduct);
            this.removeCommand = new DelegateCommand(RemoveProduct, CanRemoveProduct);
        }


        public void Initialize()
        {
            productViewModel.PropertyChanged += ProductViewModelPropertyChanged;

            IProductListView productListView = container.GetExportedValue<IProductListView>();
            productListViewModel = new ProductListViewModel(productListView, entityService.Products);
            productListViewModel.AddNewCommand = addNewCommand;
            productListViewModel.RemoveCommand = removeCommand;
            productListViewModel.PropertyChanged += ProductListViewModelPropertyChanged;

            shellViewModel.ProductListView = productListViewModel.View;
            shellViewModel.ProductView = productViewModel.View;

            productListViewModel.SelectedProduct = productListViewModel.Products.FirstOrDefault();
        }

        private bool CanAddNewProduct() { return productViewModel.IsValid; }

        private void AddNewProduct()
        {
            int ProductId;
            if (this.entityService.Products.Count == 0)
            {
                ProductId = 1;
            }
            else
            {
                ProductId = this.entityService.Products
                                            .Select(x=>x.ProductID)
                                            .Max() + 1;
            }
            Product product = Product.CreateProduct(ProductId, "", 0);
            entityService.Products.Add(product);

            productListViewModel.SelectedProduct = product;
            productViewModel.Focus();
        }

        private bool CanRemoveProduct() { return productListViewModel.SelectedProduct != null; }

        private void RemoveProduct()
        {
            foreach (Product product in productListViewModel.SelectedProducts.ToArray())
            {
                entityService.Products.Remove(product);
            }
        }


        private void UpdateCommands()
        {
            addNewCommand.RaiseCanExecuteChanged();
            removeCommand.RaiseCanExecuteChanged();
        }

        private void ProductListViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "SelectedProduct")
            {
                productViewModel.Product = productListViewModel.SelectedProduct;
                UpdateCommands();
            }
        }

        private void ProductViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsValid")
            {
                UpdateCommands();
            }
        }
    }
}
